package edu.osu.cse.c651.cryptochess;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyStore;
import org.apache.http.conn.ssl.SSLSocketFactory;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;

/**
 * This Controller sends and receives ChessBoards between the opposing players,
 * before and after moves are made, respectively.
 * 
 * @author Team Pawned
 * 
 */
public class ConnectionController {

	/**
	 * The opponent User
	 */
	private User opponent;

	/**
	 * The GameActivity that this controller must relay information to
	 */
	private GameActivity parent;

	/**
	 * Constructor
	 * 
	 * @param parent
	 *            the GameActivity where data must be sent
	 * @param opponent
	 *            the opponent User
	 */
	public ConnectionController(GameActivity parent, User opponent) {
		this.parent = parent;
		this.opponent = opponent;
	}

	/**
	 * Sends the ChessBoard to the opponent User
	 * 
	 * @param board
	 *            the ChessBoard
	 */
	public void send(ChessBoard board) {
		SendBoard sb = new SendBoard();
		sb.doInBackground(board);
	}

	/**
	 * Initiates the receipt of the ChessBoard from the opponent
	 */
	public void startReceive() {
		ReceiveBoard rb = new ReceiveBoard();
		rb.execute((Void) null);
	}

	/**
	 * Called by the send method, this class allows the ChessBoard to be sent in
	 * an asynchronous task, so as not to affect the application's performance
	 * 
	 * @author Team Pawned
	 * 
	 */
	private class SendBoard extends AsyncTask<ChessBoard, Void, Void> {

		@Override
		protected Void doInBackground(ChessBoard... arg0) {
			// Creates SSL socket over regular socket and sends the ChessBoard
			InetAddress ip = opponent.getIpAddress();
			try {
				SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
				Socket phoneSocket = new Socket(ip, 54321);
				 Socket secureSocket = sf.createSocket(phoneSocket,
						 ip.getHostName(), 54321, true);
				OutputStream cout = secureSocket.getOutputStream();
				for (int i = 0; i < 8; i++) {
					for (int j = 0; j < 8; j++) {
						Piece square = arg0[0].getPiece(i, j);
						String name;
						String color;
						if (square == null) {
							color = "0";
							name = "null";
						} else {
							if (square.color() == Color.WHITE) {
								color = "0";
								name = square.name().toString();
							} else {
								color = "1";
								name = square.name().toString();
							}
						}
						byte[] byteBoard = (color + name + "|").getBytes();
						cout.write(byteBoard);
					}
				}
				secureSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

	}

	/**
	 * Called by the startReceive method, this class allows the ChessBoard to be
	 * received in an asynchronous task, so as not to affect the application's
	 * performance
	 * 
	 * @author Team Pawned
	 * 
	 */
	private class ReceiveBoard extends AsyncTask<Void, ChessBoard, ChessBoard> {

		@Override
		protected ChessBoard doInBackground(Void... params) {
			ChessBoard board = new ChessBoard();
			// Creates SSL socket over regular socket and receives and returns
			// the chessboard
			try {
				// SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
				ServerSocket serveSocket = new ServerSocket(54321);
				ServerSocket serveSocket2 = new ServerSocket(54321);
				while (true) {
					Socket phoneSocket = serveSocket.accept();
					Socket phoneSocket2 = serveSocket2.accept();
					InputStream cin = phoneSocket2.getInputStream();
					for (int i = 0; i < 8; i++) {
						for (int j = 0; j < 8; j++) {
							char c;
							char d;
							c = (char) cin.read();
							if (c == '$')
								return null;
							d = (char) cin.read();
							String name = "";
							while (d != '|') {
								name += d;
								d = (char) cin.read();
							}
							if (name.equals("King")) {
								if (c == '0') {
									King piece = new King(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									King piece = new King(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else if (name.equals("Queen")) {
								if (c == '0') {
									Queen piece = new Queen(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									Queen piece = new Queen(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else if (name.equals("Pawn")) {
								if (c == '0') {
									Pawn piece = new Pawn(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									Pawn piece = new Pawn(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else if (name.equals("Rook")) {
								if (c == '0') {
									Rook piece = new Rook(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									Rook piece = new Rook(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else if (name.equals("Bishop")) {
								if (c == '0') {
									Bishop piece = new Bishop(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									Bishop piece = new Bishop(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else if (name.equals("Knight")) {
								if (c == '0') {
									Knight piece = new Knight(Color.WHITE);
									board.setSquare(piece, i, j);
								} else {
									Knight piece = new Knight(Color.BLACK);
									board.setSquare(piece, i, j);
								}
							} else
								board.setSquare(null, i, j);
						}
					}
					publishProgress(board);
					phoneSocket2.close();
				}
				// serveSocket.close();
				// return board;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(ChessBoard... board) {
			ChessBoard cb = board[0];
			try {
				parent.receiveBoard(cb);
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}